package com.lagou.lesson2.core.config;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.*;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @author ceven
 */
public class XMLBeanConfigParser {

    /**
     * 解析配置文件，返回需要扫描的class
     * @param inputStream
     * @return
     * @throws Exception
     */
    public static Set<String> parseBeanScanner(InputStream inputStream) throws Exception {
        Document document = new SAXReader().read(inputStream);
        Element rootElement = document.getRootElement();

        //解析mapper文件中的查询语句
        List<Element> scannerElement = rootElement.selectNodes("//bean-scanner");




        Set<Class<?>> set = new HashSet<>();
        for (Element element : scannerElement) {
            String aPackage = element.attributeValue("package").trim();
            Set<Class<?>> classSet = getClasses(aPackage);
            set.addAll(classSet);
        }


        Set<String> resultSet = new HashSet<>();
        for (Class<?> aClass : set) {
            resultSet.add(aClass.getName());
        }


        return resultSet;
    }

    /**
     * 获取包下面的所有 class
     * @param pack
     * @return
     */
    public static Set<Class<?>> getClasses(String pack){
        System.out.println("pack=" + pack);
        // 第一个class类的集合
        Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
        // 是否循环迭代
        boolean recursive = true;
        // 获取包的名字 并进行替换
        String packageName = pack;
        String packageDirName = packageName.replace('.', '/');
        // 定义一个枚举的集合 并进行循环来处理这个目录下的things
        Enumeration<URL> dirs;
        List<Class<?>> allClass = new ArrayList<>();
        try{
            dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
            // 循环迭代下去
            while (dirs.hasMoreElements()) {
                URL url = dirs.nextElement();
                File file = new File(url.getFile());
                laodClassByFile(file, pack, allClass);
            }

            classes.addAll(allClass);


        } catch (IOException e){
            e.printStackTrace();
        }

        return classes;
    }


    public static void laodClassByFile(File file, String packageName, List<Class<?>> allClassList) {
        if(file.isDirectory()) {
            file.listFiles(new FilenameFilter() {
                @Override
                public boolean accept(File file, String name) {
                    return file.getName().endsWith(".class");
                }
            });
            File[] files = file.listFiles();
            for (File file1 : files) {
                laodClassByFile(file1, packageName + "." + file1.getName(), allClassList);
            }
        } else {
            String fileName = file.getName();
            String  clazz = packageName.substring(0, packageName.length() - ".class".length());
            try {
                /*Class clz = Class.forName(clazz);
                allClassList.add(clz);*/
                // 经过群里同学交流，这里用Class.forName有一些不好，会触发static 初始化，没有使用classLoader的load干净</span>
                allClassList.add(Thread.currentThread().getContextClassLoader().loadClass(clazz));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
